package com.origin.learn.redisson;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description: 构造transwarp更新语句的工具类
 * @Date: 2020/2/13
 * @Time: 13:20
 * @Created by:   dingtao
 * @Modified by:
 * @Modified at:
 */
@Slf4j
public class TranswarpSqlUtil {

    /**
     * 索引名称
     */
    private String indexName;

    /**
     * 值集
     */
    private Map<String, Object> values;

    /**
     * 主键名称
     */
    private String idKey;

    /**
     * sql语句
     */
    private StringBuilder sql;


    public static TranswarpSqlUtil builder(){
        return new TranswarpSqlUtil();
    }

    public TranswarpSqlUtil setIndexName(String indexName){
        this.indexName = indexName;
        return this;
    }

    public TranswarpSqlUtil setValues(Map<String, Object> values){
        this.values = values;
        return this;
    }

    public TranswarpSqlUtil setIdKey(String idKey){
        this.idKey = idKey;
        return this;
    }


    /**
     * 准备更新语句
     * @return
     */
    public TranswarpSqlUtil prepareUpdate(){
        sql = new StringBuilder();
        if (values.size()==0){
            return this;
        }else {
            String id = String.valueOf(values.get(idKey));
            sql.append("update table ").append(indexName).append(" set (");

            List<String> updateValueList =
                    values.entrySet().stream()
                            //清除id列
                            .filter(entry -> !entry.getKey().equalsIgnoreCase(id))
                            //转化为key='value'格式
                            .map(entry -> entry.getKey().concat("='").concat(String.valueOf(entry.getValue())).concat("'"))
                            .collect(Collectors.toList());
            sql.append(StringUtils.join(updateValueList, ", "));

            sql.append(" where ").append(idKey).append(" = '").append(id).append("'");
        }
        return this;
    }

    public String toSql(){
//        log.error("++++++++++SQLutil\n"+ JSONObject.toJSONString(this.sql));
        String resultSql = sql.toString();
        sql = null; //help for GC
//        log.error("++++++++++resultSql\n"+ resultSql);
        return resultSql;
    }

    public final static class RegexHelper{
        /**
         * 需要转化为星环查询语句的正则表达式
         */
        private static String[] NEED_TRANSFORM_TO_TRANSWARP_PATTERN = {
                //key like'value'
                //key like 'value'
                "(?<fieldName>[a-zA-Z_]+)\\s+like\\s?(?<value>'[^']+')",
                //key like"value"
                //key like "value"
                "(?<fieldName>[a-zA-Z_]+)\\s+like\\s?(?<value>\"[^\"]+\")",
                //key = 'value', key= 'value', key ='value', key='value'
                "(?<fieldName>[a-zA-Z_]+)\\s?=\\s?(?<value>'[^']+')",
                "(?<fieldName>[a-zA-Z_]+)\\s?=\\s?(?<value>\"[^\"]+\")",
                // key=111 ...
                "(?<fieldName>[a-zA-Z_]+)\\s?=\\s?(?<value>\\d+)",
        };
        private static Pattern[] PATTERNS=null;
        static {
            PATTERNS = new Pattern[NEED_TRANSFORM_TO_TRANSWARP_PATTERN.length];
            for (int i = 0; i < NEED_TRANSFORM_TO_TRANSWARP_PATTERN.length; i++) {
                PATTERNS[i] = Pattern.compile(NEED_TRANSFORM_TO_TRANSWARP_PATTERN[i]);
            }
        }

        /**
         * 将原生sql语句，以括号进行分割
         * @param var
         * @return
         */
        public static List<String> splitWithBrackets(String var){

            List<String> withoutBracketsList = new LinkedList<>();
            char[] chars = var.toCharArray();
            Stack<Character> stack = new Stack<>();
            Stack<Character> helpToReverseStack = new Stack<>();
            for (int i = 0; i < chars.length; i++) {
                char temp = chars[i];
                if (temp!=')'){
                    stack.push(temp);
                }
                else {
                    helpToReverseStack.clear();
                    char peek = stack.pop();
                    while (peek!='('){
                        helpToReverseStack.push(peek);
                        peek = stack.pop();
                    }
                    char[] sqlChars = new char[helpToReverseStack.size()];
                    for (int j = 0; j < sqlChars.length; j++) {
                        sqlChars[j] = helpToReverseStack.pop();
                    }
                    withoutBracketsList.add(new String(sqlChars));
                }
            }
            if (!stack.isEmpty()){
                char[] sqlChars = new char[stack.size()];
                for (int i = sqlChars.length-1; i >=0 ; i--) {
                    sqlChars[i] = stack.pop();
                }
                withoutBracketsList.add(new String(sqlChars));
            }
            return withoutBracketsList;
        }


        /**
         * 获得var中第一个满足key = value, key like value格式的片段
         * @param var
         * @return
         */
        public static List<String> getConditionPart(String var){
            var = var.trim();
            if ("and".equals(var)||"or".equals(var)){
                return new ArrayList<>();
            }
            // 去除字符串开头的 and
            if (var.startsWith("and ")){
                var = var.substring(4);
            }else if (var.startsWith("or ")){
                var = var.substring(3);
            }
            if (var.length()==0){
                return new ArrayList<>();
            }

            Stack<Character> stack = new Stack<>();
            char[] helper;
            boolean flag = false;
            for (int i = 0; i < var.length(); i++) {
                char temp = var.charAt(i);
                if (temp=='\''||temp=='"'){
                    stack.push(temp);
                    if (!stack.isEmpty()&&stack.peek()!='\\'){
                        if (!flag){
                            //暂时还未放入查询值的左引号
                            flag = true;
                        }
                        else {
                            break;
                        }
                    }
                }else {
                    stack.push(temp);
                }
            }
            helper = new char[stack.size()];
            for (int j = stack.size()-1; j >=0 ; j--) {
                helper[j] = stack.pop();
            }
            String conditionPart = new String(helper);

            // 存放结果的列表
            List<String> result;
            result = Stream.of(conditionPart).collect(Collectors.toList());
            var = var.substring(conditionPart.length());
            List<String> sub = getConditionPart(var);
            if (sub.size()!=0) {
                result.addAll(sub);
            }
            return result;
        }


        /**
         * 获取key = value , key like value 中的key，以及替换后的星环es高亮查询语句
         * @param var
         * @return
         */
        public static Map<String, String> testRegex(String var, String highLightStyle){
            Map<String, String> result = new HashMap<>(2);
            for (int i = 0; i < NEED_TRANSFORM_TO_TRANSWARP_PATTERN.length; i++) {
                String regex = NEED_TRANSFORM_TO_TRANSWARP_PATTERN[i];
                if (var.matches(regex)){
                    try {
                        result.put("src", var);
                        Matcher matcher = PATTERNS[i].matcher(var);
                        matcher.find();
                        String fieldName = matcher.group("fieldName");
                        result.put("fieldName", fieldName);
                        String value = matcher.group("value");

                        StringBuilder stringBuilder = new StringBuilder();
                        stringBuilder.append(" contains (").append(fieldName).append(", ").append(value)
                                .append(", 'highlight', '<idss-span style=\"").append(highLightStyle).append("\">, ")
                                .append("'</idss-span>') ");
                        result.put("sql", stringBuilder.toString());

                        break;
                    }catch (Exception e){
                        log.error("获取["+var+"]中的字段和值出错:\n"+e);
                    }
                }
            }

            return result;
        }


    }


}
